package com.ciaojian.client.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ciaojian.client.pay.WxPayBeanFactory;
import com.ciaojian.client.service.*;
import com.ciaojian.core.constant.RedisConstant;
import com.ciaojian.core.enums.business.*;
import com.ciaojian.core.mapper.DyRecordMapper;
import com.ciaojian.core.mapper.UserMemberMapper;
import com.ciaojian.core.model.*;
import com.ciaojian.core.util.LogUtil;
import com.ciaojian.core.util.RedisUtil;
import com.ciaojian.pay.core.kit.WxPayKit;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Optional;

/**
 * @author Atlakyn
 */
@Api(tags = "回调 Controller", hidden = true)
@RestController
@Slf4j
@RequestMapping("/notify")
public class NotifyController {
    @Resource
    private UserMemberServiceImpl<UserMemberMapper, UserMember> userMemberService;
    @Resource
    private WorkerInviteServiceImpl workerInviteService;
    @Resource
    private CouponCodeServiceImpl couponCodeService;
    @Resource
    private CouponServiceImpl couponService;
    @Resource
    private MemberOrderServiceImpl memberOrderService;
    @Resource
    private OrderServiceImpl orderService;
    @Resource
    private NotifyServiceImpl notifyService;
    @Resource
    private UserServiceImpl userService;
    @Resource
    private MemberServiceImpl memberService;
    @Resource
    private DyRecordServiceImpl<DyRecordMapper, DyRecord> dyRecordService;
    @Resource
    private MemberDetailServiceImpl memberDetailService;
    @Resource
    private OrderCommissionServiceImpl orderCommissionService;

    @PostMapping("/charge")
    private void chargeNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String notifyXml = getNotifyXml(request);
        Map<String, Object> map = WxPayKit.xmlToMap(notifyXml);

        //订单编号
        String orderNo = map.get("out_trade_no").toString();
        Order order = orderService.getByOrderNo(orderNo);

        if (order != null && order.getStatus().equals(OrderStatusEnum.wait_notify)) {
            WxPayBase wxPayBean = WxPayBeanFactory.getInstance(userService.getUserInviterStore(order.getUserId()), 1);
            if (WxPayKit.verifyNotify(map, wxPayBean.getKey())) {
                notifyService.chargeNotify(order);
            }
        }

        // 通知微信回调成功
        pushNotifyXml(response);
    }

    @ApiOperation(value = "购买产品组回调", hidden = true)
    @PostMapping("/product-group")
    public void productGroupNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String notifyXml = getNotifyXml(request);
        Map<String, Object> map = WxPayKit.xmlToMap(notifyXml);

        //订单编号
        String orderNo = map.get("out_trade_no").toString();
        Order order = orderService.getByOrderNo(orderNo);

        if (order != null && order.getStatus().equals(OrderStatusEnum.wait_notify)) {
            WxPayBase wxPayBean = WxPayBeanFactory.getInstance(userService.getUserInviterStore(order.getUserId()), 0);
            if (WxPayKit.verifyNotify(map, wxPayBean.getKey())) {
                notifyService.productGroupNotify(order);
            }
        }

        // 通知微信回调成功
        pushNotifyXml(response);
    }

    @ApiOperation(value = "会员卡微信支付回调接口", hidden = true)
    @PostMapping("/wxNotify/member-card")
    public void memberCardPayNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String notifyXml = getNotifyXml(request);
        Map<String, Object> map = WxPayKit.xmlToMap(notifyXml);

        LogUtil.writePayLog(">>>购买会员卡微信支付回调通知>>>微信返回参数->{params:{}}", map);
        //订单编号
        String orderNo = map.get("out_trade_no").toString();

        // 根据订单号查询会员卡绑定的用户信息
        MemberOrder memberOrder = memberOrderService.getBaseMapper().getMemberOrderByOrderNo(orderNo);

        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 注意此处签名方式需与统一下单的签名类型一致
        WxPayBase wxPayBean = WxPayBeanFactory.getInstance(userService.getUserInviterStore(memberOrder.getUserId()), 1);
        if (WxPayKit.verifyNotify(map, wxPayBean.getKey())) {
            if (memberOrder.getStatus().getValue().equals(MemberOrderStatusEnum.no_pay.getValue())) {
                //这里做回调业务
                memberOrderService.wxNotifyOfMemberCard(memberOrder);
                // 用户充值会员获得券码
                couponService.getCouponCode(memberOrder.getMemberId(), memberOrder.getUserId());
                // 通知微信收到回调
                pushNotifyXml(response);
            }
        }
    }

    /**
     * 购买会员权益回调
     *
     * @param request  request
     * @param response response
     * @throws IOException IO 异常
     */
    @ApiOperation(value = "购买会员权益回调", hidden = true)
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/member-detail")
    public void memberDetailNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String notifyXml = getNotifyXml(request);
        Map<String, Object> map = WxPayKit.xmlToMap(notifyXml);
        LogUtil.writePayLog("购买会员权益回调,回调信息:{}", map.toString());
        //获取商户系统内部订单号（即取号时生成的订单编号)
        String orderNo = map.get("out_trade_no").toString();
        // 获取订单
        Order order = orderService.lambdaQuery().eq(Order::getOrderNo, orderNo).one();
        LogUtil.writePayLog("购买会员权益回调,订单:{}", order);

        // 订单不为空 且 状态是 已支付-待回调 或者 待支付
        if (order != null && order.getStatus().equals(OrderStatusEnum.wait_notify)) {
            WxPayBase wxPayBean = WxPayBeanFactory.getInstance(userService.getUserInviterStore(order.getUserId()), 1);
            if (WxPayKit.verifyNotify(map, wxPayBean.getKey())) {
                // 权益信息
                MemberDetail memberDetail = new MemberDetail().selectById(order.getCouponId());
                // 判断用户是不是会员，若不是,新增 memberOrder 和 userMember
                Integer isUserMember = userMemberService.checkUserMember(order.getUserId());

                // 如果是澳宝权益, 不延期会员时间
                if ((checkAoBao(memberDetail.getId()) && isUserMember == 1)) {
                    // 如果已经是潮剪会员, 则不延长会员时间
                    LogUtil.writePayLog("用户{}已是会员", order.getUserId());
                }
                // 其余情况则延长会员时间
                else {
                    // 新增会员订单
                    MemberOrder memberOrder = new MemberOrder().setOrderNo(orderNo.replace("MD", ""))
                            .setUserId(order.getUserId())
                            .setStatus(MemberOrderStatusEnum.paid)
                            .setMoney(0L)
                            .setMemberId(memberDetail.getMemberId())
                            .setInviteId(workerInviteService.getWorkerIdByUserId(order.getUserId()));
                    UserMember userMember = new UserMember();
//                    // 如果不是澳宝权益则增加首单优惠
//                    if (!checkAoBao(memberDetail.getId())) {
//                        memberDiscountService.addMemberDiscount(1, order.getUserId());
//                    }
                    // 购买的会员卡
                    Member memberBuy = new Member().selectById(memberOrder.getMemberId());
                    switch (isUserMember) {
                        //0开过会员但已过期
                        case 0:
                            memberOrder.setType(MemberOrderTypeEnum.renew).insert();
                            // 对比两种会员卡的折扣谁低
                            if (!memberOrder.getMemberId().equals(userMember.getMemberId())) {
                                try {
                                    LambdaQueryWrapper<UserMember> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                                    lambdaQueryWrapper.eq(UserMember::getUserId, order.getUserId());
                                    userMember = userMember.selectOne(lambdaQueryWrapper);
                                    // 拥有的会员卡
                                    Member memberOwned = new Member().selectById(userMember.getMemberId());
                                    if (memberBuy.getId()==5 && memberOwned.getId()==5) {
                                        userMember.setDueDate(DateUtil.offset(new Date(), DateField.YEAR, 1));
                                        userMember.setMemberId(memberBuy.getId());
                                        userMember.updateById();
                                    }else if(memberBuy.getId()!=5){
                                        Member member = memberService.compareMember(memberBuy, memberOwned);
                                        userMember.setDueDate(DateUtil.offset(new Date(), DateField.YEAR, 1));
                                        userMember.setMemberId(member.getId());
                                        userMember.updateById();
                                    }
                                } catch (JsonProcessingException e) {
                                    LogUtil.writeErrorLog(e.getMessage());
                                    e.printStackTrace();
                                }
                            }
                            break;
                        //-1未开过会员
                        case -1:
                            memberOrder.setType(MemberOrderTypeEnum.non_renew).insert();

                            userMember.setUserId(order.getUserId());
                            userMember.setOrderNo(orderNo);
                            userMember.setDueDate(DateUtil.offsetMonth(new Date(), 12));
                            userMember.setMemberId(memberBuy.getId());
                            userMember.insert();
                            break;
                        //1有效会员
                        case 1:
                            userMember = userMemberService.lambdaQuery().eq(UserMember::getUserId, order.getUserId()).one();
                            memberOrder.setType(MemberOrderTypeEnum.renew).insert();
                            // 拥有的会员卡
                            Member memberOwned = new Member().selectById(userMember.getMemberId());
                            if (memberBuy.getId()==5 && memberOwned.getId()==5) {
                                Member member = memberService.compareMember(memberBuy, memberOwned);
                                LambdaQueryWrapper<UserMember> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                                lambdaQueryWrapper.eq(UserMember::getUserId, order.getUserId());
                                userMember.setMemberId(member.getId());
                                // 为会员时间延期一年
                                userMember.setDueDate(DateUtil.offset(userMember.getDueDate(), DateField.YEAR, 1)).updateById();
                            }else if(memberBuy.getId()!=5){
                                Member member = memberService.compareMember(memberBuy, memberOwned);
                                userMember.setDueDate(DateUtil.offset(new Date(), DateField.YEAR, 1));
                                userMember.setMemberId(member.getId());
                                userMember.updateById();
                            }
                            break;
                        default:
                    }
                }

                // 给用户发放优惠券
                memberDetailService.distributeCode(
                        order.getUserId(),
                        Optional.of(memberDetail),
                        order,
                        CouponCodeOriginEnum.BUY_MEMBER_DETAIL);



//                orderService.setCustomerType(order);
                // 购买会员新增提成记录
                orderCommissionService.insertIfMemberDetail(order);

                // 如果当天有使用过抖音剪发券, 则赠送一张48元的剪发券(固定券码ID:504)
                if (RedisUtil.exists(RedisConstant.USED_DOUYIN_ORDER + order.getUserId())) {
                    CouponCode code = couponCodeService.giveSingleCouponCode(504, order.getUserId(), CouponCodeOriginEnum.BUY_MEMBER_DETAIL);
                    code.setOrderId(order.getId());
                    code.updateById();
                    System.err.println("成功:" + code);
                    RedisUtil.delKey(RedisConstant.USED_DOUYIN_ORDER + order.getUserId());
                }


                // 修改订单状态
                order.setStatus(OrderStatusEnum.paid)
                        .setPayTime(new Date())
                        .setPayType("微信支付")
                        .setPayTotal(order.getGoodsTotal())
                        .setWorkerId(order.getInviterId())
                        .updateById();

                try {
                    // 首次消费,为分销员发送微信红包
                    orderService.firstConsume2(order);

                }catch (Exception e){

                }
                // 通知微信收到回调
                pushNotifyXml(response);
            }
        }
    }

    /**
     * 检查是否是首单消费
     *
     * @param userId 用户ID
     * @return 首单消费返回TRUE
     */
    private Boolean checkFirst(Integer userId) {
        // 查看是否有已完成的订单
        Integer count = orderService.lambdaQuery()
                .eq(Order::getUserId, userId)
                .in(Order::getOrderType, OrderOrderTypeEnum.NORMAL, OrderOrderTypeEnum.MEITUAN)
                .in(Order::getStatus, OrderStatusEnum.paid, OrderStatusEnum.complete)
                .count();
        if (count == 0) {
            // 查看是否有服务中的订单
            Integer c2 = orderService.lambdaQuery()
                    .eq(Order::getUserId, userId)
                    .in(Order::getOrderType, OrderOrderTypeEnum.NORMAL, OrderOrderTypeEnum.MEITUAN)
                    .in(Order::getStatus, OrderStatusEnum.waiting, OrderStatusEnum.servicing, OrderStatusEnum.wait_pay)
                    .like(Order::getType, "新人特惠")
                    .count();
            return c2 > 0;
        }

        return Boolean.FALSE;
    }

    /**
     * 获取微信回调xml
     *
     * @param request request
     * @return xml回调信息
     */
    private String getNotifyXml(HttpServletRequest request) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String line;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();
        // sb为微信返回的xml
        return sb.toString();
    }

    /**
     * 通知微信收到回调
     *
     * @param response http response
     * @throws IOException io 异常
     */
    private void pushNotifyXml(HttpServletResponse response) throws IOException {
        String resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
    }

    /**
     * 判断是否为澳宝权益
     *
     * @param memberDetailId 权益ID
     * @return 是返回True
     */
    private Boolean checkAoBao(Integer memberDetailId) {
        return (CollUtil.contains(Arrays.asList(8, 9, 10, 11, 12, 13), memberDetailId));
    }


}
